﻿Imports SMS.Framework.Core

Namespace SMS.Framework.Scientific

    ' Namespace to work with the astronomy data and operations, etc.
    Namespace Astronomy

        ''' <summary>
        ''' Class to work with the astronomy data relationship with the Moon.
        ''' The cycle of the Moon around the Earth is 29 days, 12 hours, 44 minutes, 2.8 seconds. 29.53059 days.
        ''' </summary>
        ''' <remarks></remarks>
        Public Class Moon

            ' These variables will help us to calculate the age of the Moon.
            Private Structure MonthsValues
                Dim NameMonth As String
                Dim ValueMonth As Byte
            End Structure ' MonthsValues

            ' Months with their names and values from 0 to 11
            Private Months() As MonthsValues = {New MonthsValues With {.NameMonth = "January", .ValueMonth = 0}, _
                                                New MonthsValues With {.NameMonth = "February", .ValueMonth = 1}, _
                                                New MonthsValues With {.NameMonth = "March", .ValueMonth = 0}, _
                                                New MonthsValues With {.NameMonth = "April", .ValueMonth = 1}, _
                                                New MonthsValues With {.NameMonth = "May", .ValueMonth = 2}, _
                                                New MonthsValues With {.NameMonth = "June", .ValueMonth = 3}, _
                                                New MonthsValues With {.NameMonth = "July", .ValueMonth = 4}, _
                                                New MonthsValues With {.NameMonth = "August", .ValueMonth = 5}, _
                                                New MonthsValues With {.NameMonth = "September", .ValueMonth = 7}, _
                                                New MonthsValues With {.NameMonth = "October", .ValueMonth = 7}, _
                                                New MonthsValues With {.NameMonth = "November", .ValueMonth = 9}, _
                                                New MonthsValues With {.NameMonth = "December", .ValueMonth = 9}}

            ''' <summary>
            ''' Enum list with the general phases of the moon.
            ''' New Moon - When the Moon is roughly in the same direction as the Sun, its illuminated half is facing away from the Earth, and therefore the part that faces us is all dark: we have the new moon. When in this phase, the Moon and the Sun rise and set at about the same time.
            ''' Waxing Crescent Moon - As the Moon moves around the Earth, we get to see more and more of the illuminated half, and we say the Moon is waxing. At first we get a sliver of it, which grows as days go by. This phase is called the crescent moon.
            ''' Quarter Moon (First Quarter) - A week after the new moon, when the Moon has completed about a quarter of its turn around the Earth, we can see half of the illuminated part; that is, a quarter of the Moon. This is the first quarter phase.
            ''' Waxing Gibbous Moon - During the next week, we keep seeing more and more of the illuminated part of the Moon, and it is now called waxing gibbous (gibbous means "humped").
            ''' Full Moon - Two weeks after the new moon, the moon is now halfway through its revolution, and now the illuminated half coincides with the one facing the Earth, so that we can see a full disk: we have a full moon. As mentioned above, at this time the Moon rises at the time the Sun sets, and it sets when the Sun rises. If the Moon happens to align exactly with the Earth and Sun, then we get a lunar eclipse.
            ''' Waning Gibbous Moon - From now on, until it becomes new again, the illuminated part of the Moon that we can see decreases, and we say it's waning. The first week after full, it is called waning gibbous.
            ''' Last Quarter Moon - Three weeks after new, we again can see half of the illuminated part. This is usually called last quarter.
            ''' Waning Crescent Moon - Finally, during the fourth week, the Moon is reduced to a thin sliver from us, sometimes called waning crescent.
            ''' </summary>
            ''' <remarks></remarks>
            Public Enum Phases
                NewMoon
                WaxingCrescent
                FirstQuarter
                WaxingGibbous
                FullMoon
                WanningGibbous
                LastQuarter
                WanningCrescent
            End Enum ' Phases

            ''' <summary>
            ''' The Epact of the Moon, is an internal value relationship with the Moon. Each year, we will have a new Epact value.
            ''' </summary>
            ''' <param name="year"></param>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Function EpactValue(ByVal year As Integer) As Byte
                Dim rest As Integer = year Mod 19
                Dim value As Byte = rest * 11
                Do While value > 29
                    value -= 30
                Loop
                ' Substract 1 to the result
                If value <> 0 Then
                    value -= 1
                Else
                    value = 29
                End If
                ' Return the value of the Epact of the Moon
                Return value
            End Function ' EpactValue

            ''' <summary>
            ''' The Epact of the Moon, is an internal value relationship with the Moon. Each year, we will have a new Epact value.
            ''' </summary>
            ''' <param name="dateValue">Date to calculate the Epact year of the Moon.</param>
            ''' <returns>Returns the value of the Epact.</returns>
            ''' <remarks></remarks>
            Public Function EpactValue(ByVal dateValue As Date) As Byte
                ' Call to EpactaYear function with year parameter,
                ' and return the value of the Epacta.
                Return EpactValue(dateValue.Year)
            End Function ' EpactYear

            ''' <summary>
            ''' Calculates the age of the Moon.
            ''' Another feature about the age of the moon is the Meton cycle.
            ''' The Meton cycle repeat the same phases in the same date each 19 years.
            ''' </summary>
            ''' <param name="dateValue">Date to calculate the age of the Moon.</param>
            ''' <returns>Returns the value of the age of the Moon.</returns>
            ''' <remarks></remarks>
            Public Function Age(ByVal dateValue As Date) As Double
                ' Date
                Dim dayData As Byte = dateValue.Day
                Dim monthData As Byte = dateValue.Month
                Dim yearData As Integer = dateValue.Year
                ' Time
                Dim hoursData As Byte = dateValue.Hour
                Dim minutesData As Byte = dateValue.Minute
                Dim secondsData As Byte = dateValue.Second
                ' Get the Epacta value of the year
                Dim value As Double = EpactaValue(yearData)
                ' Add the days
                value += dayData
                ' Add the months value according with the Months structure
                value += Months(monthData - 1).ValueMonth
                ' Add 1 if the year is bisiest
                value += If(Calculate.LeapYear(yearData), 1, 0)
                ' While the value is greater than 29, substract 30 to the value
                While value > 29
                    value -= 30
                End While
                ' Add the time
                Dim portionMoonAge As Double = (hoursData * 3600 + _
                                                minutesData * 60 + _
                                                secondsData) / 86400
                ' Return the final value
                Return value + portionMoonAge
            End Function ' Age

            ''' <summary>
            ''' Calculates the luminosity of the Moon.
            ''' </summary>
            ''' <param name="dateValue">Date to calculate the luminosity of the Moon. You can use a large date (date + time) too.</param>
            ''' <returns>Returns the luminosity value in a double value.</returns>
            ''' <remarks></remarks>
            Public Function Luminosity(ByVal dateValue As Date) As Double
                ' Indicates the luminosity of the Moon in the date passed as parameter
                Dim ageValue As Single = Age(dateValue)
                ' We get the light (lit) value of the Moon
                If ageValue > 14.8347225 Then
                    Return 200 - (ageValue * 100) / 14.8347225
                Else
                    Return (ageValue * 100) / 14.8347225
                End If
                ' Return the luminosity value of the Moon
                Return (ageValue * 100) / 14.8347225
            End Function ' Luminosity

            Public Function Phase(ByVal dateValue As Date) As Phases
                ' Indicates the phase of the Moon in the date passed as parameter
                ' In the first step will get the integer value of the age of the moon
                Dim phaseValue As Byte = Age(dateValue)
                ' In the second step will process the age with the moon phase
                Select Case phaseValue
                    Case 0 To 3
                        Return Phases.NewMoon
                    Case 4 To 6
                        Return Phases.WaxingCrescent
                    Case 7 To 9
                        Return Phases.FirstQuarter
                    Case 10 To 13
                        Return Phases.WaxingGibbous
                    Case 14 To 17
                        Return Phases.FullMoon
                    Case 18 To 21
                        Return Phases.WanningGibbous
                    Case 22 To 25
                        Return Phases.LastQuarter
                    Case 26 To 29
                        Return Phases.WanningCrescent
                End Select
            End Function ' Phase

        End Class ' Moon

    End Namespace ' Namespace :: SMS.Framework.Scientific.Astronomy

End Namespace ' Namespace :: SMS.Framework.Scientific